import 'package:flutter/material.dart';
import 'package:flutter_lui/flutter_lui.dart';
import 'package:flutter_lui/src/l_style.dart';

class LPasswordGrid extends StatefulWidget {
  /// 密码格数量
  final int? gridLimit;

  /// 密码格宽度
  final double? gridWidth;

  /// 密码格圆角
  final double? gridBorderRadius;

  /// 密码格边框颜色
  final Color? gridBorderColor;

  /// 密码格展示字符串
  final String? gridShowStr;

  /// 输入内容变化时触发
  final Function(String value)? onChange;

  /// 输入长度为 gridLimit时触发
  final Function(String value)? onComplete;
  const LPasswordGrid(
      {this.gridLimit,
      this.gridWidth,
      this.gridBorderRadius,
      this.gridBorderColor,
      this.gridShowStr,
      this.onChange,
      this.onComplete,
      Key? key})
      : super(key: key);
  @override
  State<StatefulWidget> createState() => _LPasswordGrid();
}

class _LPasswordGrid extends State<LPasswordGrid>
    with SingleTickerProviderStateMixin {
  String _value = '';
  final FocusNode _focusNode = FocusNode();
  TextEditingController? _controller;
  late AnimationController _controllerAnimation;
  late Animation<double> _animation;
  double animationValue = 0;
  @override
  void initState() {
    super.initState();
    _controller = TextEditingController();
    _controllerAnimation = AnimationController(
        vsync: this,
        lowerBound: 0,
        upperBound: 1,
        animationBehavior: AnimationBehavior.preserve,
        duration: const Duration(milliseconds: 500));
    _controllerAnimation.addListener(() {
      setState(() {
        animationValue = _controllerAnimation.value;
      });
    });
    _animation = Tween(begin: 0.0, end: 1.0).animate(_controllerAnimation);
    _animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controllerAnimation.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controllerAnimation.forward();
      }
    });
    _controllerAnimation.forward();
  }

  @override
  dispose() {
    _controllerAnimation.dispose();
    _focusNode.dispose();
    if (_controller != null) {
      _controller!.dispose();
      _controller = null;
    }
    super.dispose();
  }

  handleChange(String value) {
    var changeRes = value;
    if (changeRes.length > (widget.gridLimit ?? 6)) {
      changeRes = changeRes.substring(0, widget.gridLimit ?? 6);
      _controller?.text = changeRes;
      _controller?.selection =
          TextSelection.fromPosition(TextPosition(offset: changeRes.length));
    }
    setState(() {
      _value = changeRes;
    });
    if (widget.onChange != null) {
      widget.onChange!(changeRes);
    }
    if (value.length >= (widget.gridLimit ?? 6) && widget.onComplete != null) {
      widget.onComplete!(changeRes.substring(0, widget.gridLimit ?? 6));
    }
  }

  @override
  Widget build(BuildContext context) {
    final useLimit = widget.gridLimit ?? 6;
    final useWidth = widget.gridWidth ?? lrpx(40);
    final useBorderRadius = widget.gridBorderRadius ?? lrpx(4);
    final useBorderColor = widget.gridBorderColor ?? LUI.instance.borderColor;
    final useShowStr = widget.gridShowStr ?? '●';
    return Stack(
      alignment: Alignment.center,
      children: [
        LBox(
          height: useWidth + rpx(2),
          direction: BoxDirections.horizontal,
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: List.generate(useLimit, (index) {
            double cursor = _value.length == index ||
                    (_value.length == useLimit && index == useLimit - 1)
                ? animationValue
                : 0;
            if (!_focusNode.hasFocus) {
              cursor = 0;
            }
            return LBox(
                width: useWidth,
                height: useWidth,
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                direction: BoxDirections.horizontal,
                border: const [true],
                borderSide: BorderSide(width: lrpx(1), color: useBorderColor),
                borderRadius: [useBorderRadius],
                fontSize: useWidth / 2,
                children: [
                  _value.length > index ? useShowStr : '',
                  LBox(
                      width: rpx(1),
                      height: useWidth / 2,
                      backgroundColor:
                          LUI.instance.borderColor.withOpacity(cursor))
                ]);
          }),
        ),
        Opacity(
          opacity: 0,
          child: LInput(
            focusNode: _focusNode,
            controller: _controller,
            isDense: true,
            padding: [(useWidth - rpx(18)) / 2],
            value: _value,
            onChange: handleChange,
          ),
        )
      ],
    );
  }
}
